The most vexing parse is a specific form of syntactic ambiguity resolution in the C++ programming language. The term was used by Scott Meyers in Effective STL (2001).[1] It is formally defined in section 6.8 of the C++ language standard.[2]
Contents |
An example is:
class Timer { public: Timer(); }; class TimeKeeper { public: TimeKeeper(const Timer& t); int get_time(); }; int main() { TimeKeeper time_keeper(Timer()); return time_keeper.get_time(); }
The line
TimeKeeper time_keeper(Timer());
could be disambiguated either as
Most programmers expect the first, but the C++ standard requires it to be interpreted as the second.
For example, g++ gives the following error message:
$ g++ -c time_keeper.cc time_keeper.cc: In function ‘int main()’: time_keeper.cc:15: error: request for member ‘get_time’ in ‘time_keeper’, which is of non-class type ‘TimeKeeper(Timer (*)())’
Clang++ provides a useful warning:
$ clang++ time_keeper.cc time_keeper.cc:14:25: warning: parentheses were disambiguated as a function declarator TimeKeeper time_keeper(Timer()); ^~~~~~~~~
One way to force the compiler to consider this as a variable definition is to add an extra pair of parentheses:
TimeKeeper time_keeper( (Timer()) );
An even simpler example appears when a functional cast is intended to convert an expression for initializing a variable or passing to a constructor parameter
void f(double adouble) { int i(int(adouble)); }
In this case, the parentheses around "adouble" are superfluous and the declaration of "i" is again a function declaration equivalent to the following
// takes an integer and returns an integer int i(int adouble);
To disambiguate this in favour of a variable declaration, the same technique can be used as for the first case above. Another solution is to use the cast notation or to use a named cast
// declares a variable called 'i' int i(static_cast<int>(adouble));
Using the new uniform initialization syntax introduced in C++11 solves this issue (and many more headaches related to initialization styles in C++).
The problematic code is then unambiguous when braces are used:
TimeKeeper time_keeper{Timer()};